/**
 * 
 */
package soa.security.mgr.service.impl;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.ldap.query.SearchScope;
import org.springframework.ldap.support.LdapNameBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import soa.security.Constants;
import soa.security.domain.Organization;
import soa.security.domain.Organization.Organizations;
import soa.security.domain.OrganizationUnit;
import soa.security.domain.Region;
import soa.security.exception.AdapterException;
import soa.security.exception.OrganizationException;
import soa.security.mgr.service.OrganizationMgrService;
import soa.security.util.BeanUtils;
import soa.security.util.JaxbUtils;
import soa.security.util.PinYin4jUtil;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author Cre.Gu
 *
 */
@Service
@PropertySource(value = { "classpath:/ldap.properties" })
public class OrganizationMgrServiceImpl extends BaseMgrServiceImpl implements
		OrganizationMgrService {
	protected final org.slf4j.Logger log = org.slf4j.LoggerFactory
			.getLogger(this.getClass());

	@Value("#{ environment['ldap.backup.path'] }")
	private String ldapBackupPath;
	@Value("#{ environment['ldap.base'] }")
	private String ldapBase;

	private String ldapBackupLdif = "security-ldap-data.ldif";

	@Override
	public void addOrganization(String regionDn, Organization a)
			throws OrganizationException {
		try {
			if (StringUtils.isBlank(a.getBid())) {
				a.setBid("OR" + findMaxNumber(Organization.class));
			}
			validate(a);

			a.setDn(a.buildDn(regionDn));
			try {
				Region region = regionDao.findByDn(regionDn);
				a.setRegionCode(region.getCode());
			} catch (Exception e) {
			}

			organizationDao.create(a);

			initEntryUnits(a);
		} catch (Exception e) {
			wrapException(e);
		}
	}

	@Override
	public void updateOrganization(Organization a) throws OrganizationException {
		try {
			validateOrganization(a.getBid());

			Organization up = organizationDao.findByPrimaryKey(a.getBid());
			BeanUtils.copyPropertiesWithoutNull(a, up);
			a = up;

			validate(a);
			a.setDn(organizationDao.findByPrimaryKey(a.getBid()).getDn());
			organizationDao.update(a);
		} catch (Exception e) {
			wrapException(e);
		}
	}

	private void validate(Organization d) {
		Assert.hasText(d.getBid(), "机构唯一编码不能为空");
		Assert.hasText(d.getName(), "机构名称不能为空");
		Assert.hasText(d.getOrganizationCode(), "组织机构代码不能为空");
		Assert.hasText(d.getCode(), "机构编码不能为空");
		
		if (d.getEname() == null || "".equals(d.getEname())) {
			d.setEname(PinYin4jUtil.converterToFirstSpell(getDictionaryName(d.getName())));
		}
		BeanUtils.blank2Null(d);
	}
	
	/**
	 * 去除括号及其中内容
	 * 
	 * @param name
	 * @return String
	 */
	private String getDictionaryName(String name) {
		name = name.replace("（", "(");
		name = name.replace("）", ")");
		name = name.replaceAll("\\([^)]+\\)", "");
		return name;
	}

	@Override
	public void initEntryUnits(Organization organization) {
		organizationUnitDao.create(organization,
				OrganizationUnit.build(Constants.DEPARTMENT, "部门的分组"));
		organizationUnitDao.create(organization,
				OrganizationUnit.build(Constants.PERSON, "人员的分组"));
		organizationUnitDao.create(organization,
				OrganizationUnit.build(Constants.ACCOUNT, "账号的分组"));

		organizationUnitDao.create(organization,
				OrganizationUnit.build(Constants.POSITION, "岗位的分组"));
		organizationUnitDao.create(organization,
				OrganizationUnit.build(Constants.GROUP, "组的分组"));
		organizationUnitDao.create(organization,
				OrganizationUnit.build(Constants.ROLE, "角色的分组"));
		/*
		 * organizationUnitDao.create(organization,
		 * OrganizationUnit.build(Constants.SYSTEMROLE, "系统管理角色的分组"));
		 */
	}

	@Override
	public void addSubOrganization(String organizationId, Organization a)
			throws OrganizationException {
		try {
			if (StringUtils.isBlank(a.getBid())) {
				a.setBid("OR" + findMaxNumber(Organization.class));
			}
			validate(a);
			validateOrganization(organizationId);

			a.setParentBid(organizationId);
			a.setDn(LdapNameBuilder
					.newInstance(findOrganization(organizationId).getDn())
					.add(Constants.BID, a.getBid()).build());

			a.setRegionCode(findOrganization(organizationId).getRegionCode());
			organizationDao.create(a);

			initEntryUnits(a);
		} catch (Exception e) {
			wrapException(e);
		}
	}

	@Override
	public List<Organization> allSubOrganizations(String organizationId)
			throws OrganizationException {
		return allSubOrganizations(organizationId, null);
	}

	@Override
	public List<Organization> allSubOrganizations(String organizationId,
			Map<String, Object> parameters) throws OrganizationException {
		List<Organization> results = new ArrayList<Organization>();
		try {
			validateOrganization(organizationId);
			results = organizationDao.allSubOrganizations(
					organizationDao.findByPrimaryKey(organizationId),
					parameters);

			sortResult(results);
		} catch (Exception e) {
			printException(e);
		}
		return results;
	}

	@Override
	public List<Organization> getOrganization(String organizationId)
			throws OrganizationException {
		validateOrganization(organizationId);
		List<Organization> list = new ArrayList<Organization>();

		list.add(organizationDao.findByPrimaryKey(organizationId));
		return list;
	}

	@Override
	public List<Organization> adapt(String xml) throws AdapterException {
		try {
			Organizations bs = JaxbUtils.xml2Object(xml, Organizations.class);
			return bs.getOrganization();

		} catch (Exception e) {
			if (log.isDebugEnabled())
				log.debug("格式转换错误", e);
			throw new AdapterException(AdapterException.ERROR_01);
		}

	}

	@Override
	public String unadapt(List<Organization> list) throws AdapterException {
		try {
			Organizations bs = new Organizations();
			bs.addAll(list);

			return JaxbUtils.object2Xml(bs, Organizations.class);
		} catch (Exception e) {
			if (log.isDebugEnabled())
				log.debug("格式转换错误", e);
			throw new AdapterException(AdapterException.ERROR_01);
		}
	}

	@Override
	public void backUpOrganization() {
		String data = organizationDao.backupData(ldapBase);
		if (StringUtils.isBlank(ldapBackupPath))
			ldapBackupPath = FileUtils.getUserDirectory().getAbsolutePath();

		File file = new File(ldapBackupPath, ldapBackupLdif);
		try {
			FileUtils.writeStringToFile(file, data);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public Organization findByDn(String dn) {
		try {
			return organizationDao.findByDn(dn);

		} catch (Exception e) {
			printException(e);
			if (log.isDebugEnabled())
				log.debug("错误信息", e);

			return null;
		}
	}

	@Override
	public boolean deleteByDn(String dn) {
		try {
			organizationDao.deleteByDn(dn);
			return true;
		} catch (Exception e) {
			printException(e);
			if (log.isDebugEnabled())
				log.debug("错误信息", e);

			return false;
		}
	}

	@Override
	public List<Organization> allOrganizations(String baseDn)
			throws OrganizationException {
		return allOrganizations(baseDn, null);
	}

	@Override
	public List<Organization> allOrganizations(String baseDn,
			Map<String, Object> parameters) throws OrganizationException {
		List<Organization> results = new ArrayList<Organization>();
		try {
			results = organizationDao.allOrganizations(baseDn,
					defaultSearchScope, parameters);
			sortResult(results);
		} catch (Exception e) {
			printException(e);
		}
		return results;
	}

	@Override
	public List<Organization> allOrganizations4Login()
			throws OrganizationException {
		List<Organization> results = new ArrayList<Organization>();
		try {
			results = organizationDao.allOrganizations(Region.root().buildDn()
					.toString(), SearchScope.SUBTREE, null);
			sortResult(results);
		} catch (Exception e) {
			printException(e);
		}
		return results;
	}
	
	@Override
	public Organization existByCode(String code) {
		// TODO Auto-generated method stub
		try {
			List<Organization> list = organizationDao.existCode(code);
			if (list.size() > 0) {
				return list.get(0);
			}
		} catch (Exception e) {
			printException(e);
		}
		return null;
	}

	@Override
	public Organization existByOrganizationCode(String organizationCode) {
		// TODO Auto-generated method stub
		try {
			List<Organization> list = organizationDao.existOrganizationCode(organizationCode);
			if (list.size() > 0) {
				return list.get(0);
			}
		} catch (Exception e) {
			printException(e);
		}
		return null;
	}

}
